/*
Copyright © 2024 wjsmc
*/
package internal

import (
	"fmt"
	"os"
	"strings"

	"github.com/AlecAivazis/survey/v2"
	"github.com/spf13/cobra"
	"nodemessage.com/ruov-cli/config"
	"nodemessage.com/ruov-cli/consts"
	"nodemessage.com/ruov-cli/rlog"
	"nodemessage.com/ruov-cli/utils"
)

// installCmd represents the install command
var installCmd = &cobra.Command{
	Use:     "install [mysql|redis|nginx|nvm|pyenv|jdk|docker]",
	Short:   "安装各种开发环境和服务",
	Long:    `用于安装和配置各种开发环境和服务，如MySQL、Redis、Nginx等`,
	Example: "ruov install mysql\nruov install redis mysql",
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 {
			cmd.Help()
			return
		}

		// 确保安装配置文件存在
		if err := ensureInstallConfig(); err != nil {
			rlog.Logger.Fatal("确保安装配置文件存在失败: %v", err)
			return
		}

		// 处理安装命令
		for _, arg := range args {
			arg = strings.ToLower(arg)
			switch arg {
			case "mysql":
				initServiceConfig("mysql")
				installMysql()
			case "redis":
				initServiceConfig("redis")
				installRedis()
			case "nginx":
				initServiceConfig("nginx")
				installNginx()
			case "nvm":
				initServiceConfig("nvm")
				installNvm()
			case "pyenv":
				initServiceConfig("pyenv")
				installPyenv()
			case "jdk":
				initServiceConfig("jdk")
				installJdk()
			case "docker":
				initServiceConfig("docker")
				installDocker()
			default:
				rlog.Logger.Warn("不支持的安装选项: %s", arg)
			}
		}
	},
}

// ensureInstallConfig 确保安装配置文件存在
func ensureInstallConfig() error {
	// 检查配置文件是否存在
	if _, err := os.Stat(consts.InstallFile); os.IsNotExist(err) {
		// 如果不存在，创建并初始化
		err = utils.InitDefaultInstall()
		if err != nil {
			return fmt.Errorf("初始化默认安装配置失败: %v", err)
		}
	}
	return nil
}

// initServiceConfig 初始化特定服务的配置
func initServiceConfig(service string) error {
	// 加载安装配置
	install, err := utils.LoadInstall()
	if err != nil {
		return fmt.Errorf("加载安装配置失败: %v", err)
	}

	needToSave := false

	// 根据不同服务提供不同配置选项
	switch service {
	case "mysql":
		if err := configureMysql(install); err != nil {
			return err
		}
		needToSave = true
	case "redis":
		if err := configureRedis(install); err != nil {
			return err
		}
		needToSave = true
	case "nginx":
		if err := configureNginx(install); err != nil {
			return err
		}
		needToSave = true
	case "nvm":
		if err := configureNvm(install); err != nil {
			return err
		}
		needToSave = true
	case "pyenv":
		if err := configurePyenv(install); err != nil {
			return err
		}
		needToSave = true
	case "jdk":
		if err := configureJdk(install); err != nil {
			return err
		}
		needToSave = true
	case "docker":
		if err := configureDocker(install); err != nil {
			return err
		}
		needToSave = true
	default:
		rlog.Logger.Warn("未知服务类型: %s", service)
	}

	// 如果有修改，保存配置
	if needToSave {
		if err := utils.SaveInstall(install); err != nil {
			return fmt.Errorf("保存安装配置失败: %v", err)
		}
	}

	return nil
}

// configureMysql 配置MySQL
func configureMysql(install *config.Install) error {
	// 询问用户是否需要修改MySQL配置
	var confirmEdit bool
	prompt := &survey.Confirm{
		Message: "是否需要修改MySQL安装配置?",
		Default: false,
	}
	err := survey.AskOne(prompt, &confirmEdit)
	if err != nil {
		return fmt.Errorf("获取用户输入失败: %v", err)
	}

	if confirmEdit {
		// MySQL配置问题
		questions := []*survey.Question{
			{
				Name: "rootPath",
				Prompt: &survey.Input{
					Message: "MySQL安装根目录:",
					Default: install.Mysql.RootPath,
				},
			},
			{
				Name: "port",
				Prompt: &survey.Input{
					Message: "MySQL服务端口:",
					Default: fmt.Sprintf("%d", install.Mysql.Port),
				},
				Validate: survey.ComposeValidators(
					survey.Required,
					func(val interface{}) error {
						// 验证是否为数字
						str := val.(string)
						if _, err := fmt.Sscanf(str, "%d", &install.Mysql.Port); err != nil {
							return fmt.Errorf("请输入有效的端口号")
						}
						return nil
					},
				),
			},
			{
				Name: "rootDefaultPwd",
				Prompt: &survey.Password{
					Message: "MySQL默认root密码(当前:" + install.Mysql.RootDefaultPwd + "):",
				},
				Validate: survey.Required,
			},
		}

		// 使用临时结构体来接收用户输入
		answers := struct {
			RootPath       string
			Port           string
			RootDefaultPwd string
		}{}

		// 询问用户MySQL配置
		err = survey.Ask(questions, &answers)
		if err != nil {
			return fmt.Errorf("获取MySQL配置失败: %v", err)
		}

		// 更新配置
		install.Mysql.RootPath = answers.RootPath
		install.Mysql.RootDefaultPwd = answers.RootDefaultPwd
	}

	return nil
}

// configureRedis 配置Redis
func configureRedis(install *config.Install) error {
	// 询问用户是否需要修改Redis配置
	var confirmEdit bool
	prompt := &survey.Confirm{
		Message: "是否需要修改Redis安装配置?",
		Default: false,
	}
	err := survey.AskOne(prompt, &confirmEdit)
	if err != nil {
		return fmt.Errorf("获取用户输入失败: %v", err)
	}

	if confirmEdit {
		// Redis配置问题
		questions := []*survey.Question{
			{
				Name: "rootPath",
				Prompt: &survey.Input{
					Message: "Redis安装根目录:",
					Default: install.Redis.RootPath,
				},
			},
			{
				Name: "port",
				Prompt: &survey.Input{
					Message: "Redis服务端口:",
					Default: fmt.Sprintf("%d", install.Redis.Port),
				},
				Validate: survey.ComposeValidators(
					survey.Required,
					func(val interface{}) error {
						// 验证是否为数字
						str := val.(string)
						if _, err := fmt.Sscanf(str, "%d", &install.Redis.Port); err != nil {
							return fmt.Errorf("请输入有效的端口号")
						}
						return nil
					},
				),
			},
			{
				Name: "defaultPwd",
				Prompt: &survey.Password{
					Message: "Redis默认密码(可为空,当前:" + install.Redis.DefaultPwd + "):",
				},
			},
		}

		// 使用临时结构体来接收用户输入
		answers := struct {
			RootPath   string
			Port       string
			DefaultPwd string
		}{}

		// 询问用户Redis配置
		err = survey.Ask(questions, &answers)
		if err != nil {
			return fmt.Errorf("获取Redis配置失败: %v", err)
		}

		// 更新配置
		install.Redis.RootPath = answers.RootPath
		install.Redis.DefaultPwd = answers.DefaultPwd
	}

	return nil
}

// configureNginx 配置Nginx
func configureNginx(install *config.Install) error {
	// 询问用户是否需要修改Nginx配置
	var confirmEdit bool
	prompt := &survey.Confirm{
		Message: "是否需要修改Nginx安装配置?",
		Default: false,
	}
	err := survey.AskOne(prompt, &confirmEdit)
	if err != nil {
		return fmt.Errorf("获取用户输入失败: %v", err)
	}

	if confirmEdit {
		// Nginx配置问题
		questions := []*survey.Question{
			{
				Name: "setupRootPath",
				Prompt: &survey.Input{
					Message: "Nginx安装包路径:",
					Default: install.Nginx.SetupRootPath,
				},
			},
			{
				Name: "rootPath",
				Prompt: &survey.Input{
					Message: "Nginx安装根目录:",
					Default: install.Nginx.RootPath,
				},
			},
		}

		// 使用临时结构体来接收用户输入
		answers := struct {
			SetupRootPath string
			RootPath      string
		}{}

		// 询问用户Nginx配置
		err = survey.Ask(questions, &answers)
		if err != nil {
			return fmt.Errorf("获取Nginx配置失败: %v", err)
		}

		// 更新配置
		install.Nginx.SetupRootPath = answers.SetupRootPath
		install.Nginx.RootPath = answers.RootPath
	}

	return nil
}

// configureNvm 配置NVM
func configureNvm(install *config.Install) error {
	// 询问用户是否需要修改NVM配置
	var confirmEdit bool
	prompt := &survey.Confirm{
		Message: "是否需要修改NVM安装配置?",
		Default: false,
	}
	err := survey.AskOne(prompt, &confirmEdit)
	if err != nil {
		return fmt.Errorf("获取用户输入失败: %v", err)
	}

	if confirmEdit {
		// NVM配置问题
		questions := []*survey.Question{
			{
				Name: "rootPath",
				Prompt: &survey.Input{
					Message: "NVM安装根目录:",
					Default: install.Nvm.RootPath,
				},
			},
		}

		// 使用临时结构体来接收用户输入
		answers := struct {
			RootPath string
		}{}

		// 询问用户NVM配置
		err = survey.Ask(questions, &answers)
		if err != nil {
			return fmt.Errorf("获取NVM配置失败: %v", err)
		}

		// 更新配置
		install.Nvm.RootPath = answers.RootPath
	}

	return nil
}

// configurePyenv 配置Pyenv
func configurePyenv(install *config.Install) error {
	// 询问用户是否需要修改Pyenv配置
	var confirmEdit bool
	prompt := &survey.Confirm{
		Message: "是否需要修改Pyenv安装配置?",
		Default: false,
	}
	err := survey.AskOne(prompt, &confirmEdit)
	if err != nil {
		return fmt.Errorf("获取用户输入失败: %v", err)
	}

	if confirmEdit {
		// Pyenv配置问题
		questions := []*survey.Question{
			{
				Name: "rootPath",
				Prompt: &survey.Input{
					Message: "Pyenv安装根目录:",
					Default: install.Pyenv.RootPath,
				},
			},
		}

		// 使用临时结构体来接收用户输入
		answers := struct {
			RootPath string
		}{}

		// 询问用户Pyenv配置
		err = survey.Ask(questions, &answers)
		if err != nil {
			return fmt.Errorf("获取Pyenv配置失败: %v", err)
		}

		// 更新配置
		install.Pyenv.RootPath = answers.RootPath
	}

	return nil
}

// configureJdk 配置JDK
func configureJdk(install *config.Install) error {
	// 询问用户是否需要修改JDK配置
	var confirmEdit bool
	prompt := &survey.Confirm{
		Message: "是否需要修改JDK安装配置?",
		Default: false,
	}
	err := survey.AskOne(prompt, &confirmEdit)
	if err != nil {
		return fmt.Errorf("获取用户输入失败: %v", err)
	}

	if confirmEdit {
		// JDK配置问题
		questions := []*survey.Question{
			{
				Name: "packagePath",
				Prompt: &survey.Input{
					Message: "JDK安装包目录:",
					Default: install.Jdk.PackagePath,
				},
			},
		}

		// 使用临时结构体来接收用户输入
		answers := struct {
			PackagePath string
		}{}

		// 询问用户JDK配置
		err = survey.Ask(questions, &answers)
		if err != nil {
			return fmt.Errorf("获取JDK配置失败: %v", err)
		}

		// 更新配置
		install.Jdk.PackagePath = answers.PackagePath
	}

	return nil
}

// configureDocker 配置Docker
func configureDocker(install *config.Install) error {
	// Docker目前没有特定配置需要修改
	rlog.Logger.Info("Docker当前没有可配置项，使用默认配置")
	return nil
}

// installMysql 安装MySQL
func installMysql() {
	rlog.Logger.Info("开始安装 MySQL...")
	// 加载安装配置
	install, err := utils.LoadInstall()
	if err != nil {
		rlog.Logger.Error("加载安装配置失败: %v", err)
		rlog.Logger.Error("安装MySQL失败: 无法加载配置")
		return
	}

	// 检查MySQL根目录
	if install.Mysql.RootPath == "" {
		rlog.Logger.Error("MySQL根目录未配置")
		rlog.Logger.Error("安装MySQL失败: 未配置根目录")
		return
	}

	// 首先检查端口是否可用
	if !utils.IsPortAvailable(install.Mysql.Port) {
		rlog.Logger.Error("MySQL端口 %d 已被占用", install.Mysql.Port)
		rlog.Logger.Error("安装MySQL失败: 端口 %d 已被占用，请修改配置或关闭占用此端口的应用", install.Mysql.Port)
		return
	}

	// 检查目录是否存在
	if _, err := os.Stat(install.Mysql.RootPath); os.IsNotExist(err) {
		// 创建目录
		err = os.MkdirAll(install.Mysql.RootPath, os.ModePerm)
		if err != nil {
			rlog.Logger.Error("创建MySQL目录失败: %v", err)
			rlog.Logger.Error("安装MySQL失败: 无法创建目录 %s", install.Mysql.RootPath)
			return
		}
		rlog.Logger.Info("已创建MySQL目录: %s", install.Mysql.RootPath)
	}

	// TODO: 下载MySQL安装包

	// TODO: 解压安装包

	// TODO: 初始化MySQL配置

	// TODO: 启动MySQL服务

	rlog.Logger.Info("MySQL安装完成! 地址: %s:%d, 用户名: root, 密码: %s",
		"localhost", install.Mysql.Port, install.Mysql.RootDefaultPwd)
}

// installRedis 安装Redis
func installRedis() {
	rlog.Logger.Info("开始安装 Redis...")
	// 加载安装配置
	install, err := utils.LoadInstall()
	if err != nil {
		rlog.Logger.Error("加载安装配置失败: %v", err)
		rlog.Logger.Error("安装Redis失败: 无法加载配置")
		return
	}

	// 检查Redis根目录
	if install.Redis.RootPath == "" {
		rlog.Logger.Error("Redis根目录未配置")
		rlog.Logger.Error("安装Redis失败: 未配置根目录")
		return
	}

	// 首先检查端口是否可用
	if !utils.IsPortAvailable(install.Redis.Port) {
		rlog.Logger.Error("Redis端口 %d 已被占用", install.Redis.Port)
		rlog.Logger.Error("安装Redis失败: 端口 %d 已被占用，请修改配置或关闭占用此端口的应用", install.Redis.Port)
		return
	}

	// 检查目录是否存在
	if _, err := os.Stat(install.Redis.RootPath); os.IsNotExist(err) {
		// 创建目录
		err = os.MkdirAll(install.Redis.RootPath, os.ModePerm)
		if err != nil {
			rlog.Logger.Error("创建Redis目录失败: %v", err)
			rlog.Logger.Error("安装Redis失败: 无法创建目录 %s", install.Redis.RootPath)
			return
		}
		rlog.Logger.Info("已创建Redis目录: %s", install.Redis.RootPath)
	}

	// TODO: 下载Redis安装包

	// TODO: 解压安装包

	// TODO: 编译安装Redis

	// TODO: 配置Redis

	// TODO: 启动Redis服务

	if install.Redis.DefaultPwd != "" {
		rlog.Logger.Info("Redis安装完成! 地址: %s:%d, 密码: %s",
			"localhost", install.Redis.Port, install.Redis.DefaultPwd)
	} else {
		rlog.Logger.Info("Redis安装完成! 地址: %s:%d, 无密码",
			"localhost", install.Redis.Port)
	}
}

// installNginx 安装Nginx
func installNginx() {
	rlog.Logger.Info("开始安装 Nginx...")

	// 加载安装配置
	install, err := utils.LoadInstall()
	if err != nil {
		rlog.Logger.Error("加载安装配置失败: %v", err)
		rlog.Logger.Error("安装Nginx失败: 无法加载配置")
		return
	}

	// 检查Nginx根目录
	if install.Nginx.RootPath == "" {
		rlog.Logger.Error("Nginx根目录未配置")
		rlog.Logger.Error("安装Nginx失败: 未配置根目录")
		return
	}

	// 检查安装包路径
	if install.Nginx.SetupRootPath == "" {
		rlog.Logger.Error("Nginx安装包路径未配置")
		rlog.Logger.Error("安装Nginx失败: 未配置安装包路径")
		return
	}

	// 检查目录是否存在
	if _, err := os.Stat(install.Nginx.RootPath); os.IsNotExist(err) {
		// 创建目录
		err = os.MkdirAll(install.Nginx.RootPath, os.ModePerm)
		if err != nil {
			rlog.Logger.Error("创建Nginx目录失败: %v", err)
			rlog.Logger.Error("安装Nginx失败: 无法创建目录 %s", install.Nginx.RootPath)
			return
		}
		rlog.Logger.Info("已创建Nginx目录: %s", install.Nginx.RootPath)
	}

	// TODO: 下载Nginx安装包

	// TODO: 解压安装包

	// TODO: 配置Nginx

	// TODO: 启动Nginx服务

	rlog.Logger.Info("Nginx安装完成! 安装目录: %s", install.Nginx.RootPath)
}

// installNvm 安装NVM
func installNvm() {
	rlog.Logger.Info("开始安装 NVM...")
	// TODO: 实现NVM安装步骤
	rlog.Logger.Info("NVM安装完成!")
}

// installPyenv 安装Pyenv
func installPyenv() {
	rlog.Logger.Info("开始安装 Pyenv...")
	// TODO: 实现Pyenv安装步骤
	rlog.Logger.Info("Pyenv安装完成!")
}

// installJdk 安装JDK
func installJdk() {
	rlog.Logger.Info("开始安装 JDK...")
	// TODO: 实现JDK安装步骤
	rlog.Logger.Info("JDK安装完成!")
}

// installDocker 安装Docker
func installDocker() {
	rlog.Logger.Info("开始安装 Docker...")
	// TODO: 实现Docker安装步骤
	rlog.Logger.Info("Docker安装完成!")
}
